from __future__ import division

import sys, re, argparse, os.path

import stats


playlist_header = '<?xml version="1.0" ?>\n<playlist>\n<generics pointer="0"/>\n'
playlist_footer = '</playlist>\n'

def process_lines(
    lines, cl_range_nm, min_such_peaks, max_such_peaks,
    min_peaks_including_detachment, max_peaks_including_detachment,
    min_detachment_cl_nm, max_detachment_cl_nm,
    min_detachment_z_nm, max_detachment_z_nm,
    min_detachment_d_nm, max_detachment_d_nm,
    max_inner_peak_force_pn, detachment_strictly_largest,
    file_to_watch):
    how_many = 0
    min_detachment_cl_nm_code = compile(min_detachment_cl_nm, "<string>", "eval")
    max_detachment_cl_nm_code = compile(max_detachment_cl_nm, "<string>", "eval")
    min_detachment_z_nm_code = compile(min_detachment_z_nm, "<string>", "eval")
    max_detachment_z_nm_code = compile(max_detachment_z_nm, "<string>", "eval")
    min_detachment_d_nm_code = compile(min_detachment_d_nm, "<string>", "eval")
    max_detachment_d_nm_code = compile(max_detachment_d_nm, "<string>", "eval")
    selected_hkp_path = os.path.join(
        os.path.dirname(file_to_watch),
        "selected_%s_%s_%d_%d_%d_%d_%s_%s_%s_%s_%s_%s_%s_%s.hkp" % (
        cl_range_nm[0], cl_range_nm[1],
        min_such_peaks, max_such_peaks,
        min_peaks_including_detachment, max_peaks_including_detachment,
        min_detachment_cl_nm, max_detachment_cl_nm,
        min_detachment_z_nm, max_detachment_z_nm,
        min_detachment_d_nm, max_detachment_d_nm,
        max_inner_peak_force_pn, detachment_strictly_largest))
    with open(selected_hkp_path, "w") as f:
        f.write(playlist_header)
	for line in lines:
            data = stats.extract_data(line)
            if data:
                deltas = [data[i + 1][0] - data[i][0] for i in range(len(data) - 1)]
                good_deltas = [delta for delta in deltas if cl_range_nm[0] <= delta <= cl_range_nm[1]]
                such_peaks = len(good_deltas)
                locals = {"such_peaks" : such_peaks}
                if (min_such_peaks <= such_peaks <= max_such_peaks
                    and min_peaks_including_detachment <= len(data) <= max_peaks_including_detachment
                    and (not data or eval(min_detachment_cl_nm_code, {}, locals) <= data[-1][0] <= eval(max_detachment_cl_nm, {}, locals))
                    and (not data or eval(min_detachment_z_nm_code, {}, locals) <= data[-1][2] <= eval(max_detachment_z_nm, {}, locals))
                    and (not data or eval(min_detachment_d_nm_code, {}, locals) <= data[-1][3] <= eval(max_detachment_d_nm, {}, locals))
                    and (len(data) <= 1 or max(zip(*data)[1][:-1]) <= max_inner_peak_force_pn)
                    and (not detachment_strictly_largest or (len(data) >= 1 and max(zip(*data)[1]) == data[-1][1]))):
                    how_many += 1
                    f.write(line)
        f.write(playlist_footer)
    return how_many, selected_hkp_path

def main(params):
    parser = argparse.ArgumentParser()
    parser.add_argument("--processed_playlist") 
    parser.add_argument("--cl_start_nm", type=float) 
    parser.add_argument("--cl_end_nm", type=float) 
    parser.add_argument("--min_such_peaks", type=int)
    parser.add_argument("--max_such_peaks", type=int)
    parser.add_argument("--min_peaks_including_detachment", type=int, default=0)
    parser.add_argument("--max_peaks_including_detachment", type=int)
    parser.add_argument("--min_detachment_cl_nm", type=str)
    parser.add_argument("--max_detachment_cl_nm", type=str)
    parser.add_argument("--min_detachment_z_nm", type=str, default="0")
    parser.add_argument("--max_detachment_z_nm", type=str, default="9999")
    parser.add_argument("--min_detachment_d_nm", type=str, default="0")
    parser.add_argument("--max_detachment_d_nm", type=str, default="9999")
    parser.add_argument("--max_inner_peak_force_pn", type=float)
    parser.add_argument("--detachment_strictly_largest", choices=("True", "False"))
    args = parser.parse_args(params)
    print(args)

    file_to_watch = args.processed_playlist
    cl_range_nm = (args.cl_start_nm, args.cl_end_nm)
    min_such_peaks = args.min_such_peaks
    max_such_peaks = args.max_such_peaks
    min_peaks_including_detachment = args.min_peaks_including_detachment
    max_peaks_including_detachment = args.max_peaks_including_detachment
    max_detachment_cl_nm = args.max_detachment_cl_nm
    min_detachment_cl_nm = args.min_detachment_cl_nm
    max_inner_peak_force_pn = args.max_inner_peak_force_pn
    max_detachment_z_nm = args.max_detachment_z_nm
    min_detachment_z_nm = args.min_detachment_z_nm
    max_detachment_d_nm = args.max_detachment_d_nm
    min_detachment_d_nm = args.min_detachment_d_nm
    detachment_strictly_largest = {"false" : False, "true" : True}.get(
        args.detachment_strictly_largest.lower())

    with open(file_to_watch, "r") as f:
        lines = f.readlines()
    if lines:
        how_many, selected_hkp_path = process_lines(
            lines, cl_range_nm, min_such_peaks, max_such_peaks,
            min_peaks_including_detachment, max_peaks_including_detachment,
            min_detachment_cl_nm, max_detachment_cl_nm,
            min_detachment_z_nm, max_detachment_z_nm,
            min_detachment_d_nm, max_detachment_d_nm,
            max_inner_peak_force_pn, detachment_strictly_largest, file_to_watch)
        print(
            "Found %d good curves. Check them out in %s." % (
                how_many, selected_hkp_path))

if __name__ == "__main__":
    main(sys.argv[1:])
